package com.lmind.core.gps.terminal;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;

import org.junit.internal.runners.statements.RunAfters;

import com.lmind.core.gps.terminal.message.AbstractMessage;
import com.lmind.core.gps.terminal.protocol.JsonMessageCodec;
import com.lmind.core.gps.terminal.protocol.PacketCodec;
import com.lmind.core.gps.terminal.protocol.PacketConstants;

public class DefaultGatewayConnector implements GatewayConnector {
	
	private Socket socket = new Socket();
	
	private OutputStream output;
	
	private InputStream input;
	
	private ByteBuffer inputBuffer;
	
	private JsonMessageCodec objectCodec = new JsonMessageCodec();
	
	private PacketCodec packetCodec = new PacketCodec();
	
	private GatewayConnectorListener listener;

	@Override
	public void connect(InetSocketAddress address) {
		try {
			socket.connect(address);
			output = socket.getOutputStream();
			input = socket.getInputStream();
			
			inputBuffer = ByteBuffer.allocate(PacketConstants.HEADER_SIZE + PacketConstants.MAX_BODY_SIZE);
			new Thread(new ReadThread()).start();
			
		} catch (IOException e) {
			throw new GatewayException(e);
		}
	}

	@Override
	public void send(AbstractMessage message) {
		
		try {
			ByteBuffer data = packetCodec.encode(objectCodec.encode(message));
			byte[] b = new byte[data.remaining()];
			data.get(b);
			output.write(b);
			output.flush();
		} catch (Exception e) {
			throw new GatewayException(e);
		}
	}

	@Override
	public Object sendForReply(AbstractMessage message) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setListener(GatewayConnectorListener listener) {
		// TODO Auto-generated method stub

	}
	
	protected void receiveMessage(AbstractMessage message) {
		if (listener != null)
			listener.revice(message);
	}
	
	
	class ReadThread implements Runnable {

		@Override
		public void run() {
			
			try {
				while (true) {
					int b = input.read();
					if (b != -1) {
						inputBuffer.put((byte)b);
						ByteBuffer packet = packetCodec.decode(inputBuffer);
						if (packet == null)
							continue;
						AbstractMessage msg = objectCodec.decode(packet);
						receiveMessage(msg);
						inputBuffer.clear();
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
	}

}
